持續卡關debug的一天。不過至少可以紀錄一下今天弄出debug環境的筆記:
上篇提到seperated debug symbol gdb吃不進去的問題,而我們現在剛好在一個青黃不接的debug狀態下,既沒有完整的native環境、打造gdbserver要穿網路出來也很麻煩。此時比較適當的作法還是,我們必須想辦法編出一個debug build、然後使用qemu linux-user mode來配合runtime error的剖析。
此時有兩套作法,一套是必須在Alpine的world外重新打一套toolchain跟要debug的套件(白話說就是重建整個sysroot);另一套是深入Alpine的abuild/aports建置系統作處置。因為目前並不明朗是哪個環節出錯,為了避免引入太多變因,我的選擇是現在走後者。
按照Alpine的APKBUILD reference有說,可以在options
中指定nostrip
的選項、並且可以指定 nodbg
來避免製作出seperated debug symbol套件。然而這兩點我在測試apk
與musl
兩個 aports套件時,其實遇到abuilds不聽使喚的狀況:出於未知的原因,musl
依舊會被strip掉並且丟出去給 musl-dbg.apk
、而apk
則是沒有預設可以作debug build的選項。於是我最後的作法,其實是有點暴力地善用反正我有docker在管理我的建置還硬 — — 直接退版到bootstraping musl前,在APKBUILD的configure階段直接把所有subpackage幹掉、並且強行補上-g3 -O0
來建置。
在重新bootstrap出這一版debug build後,便可以成功地拿到一套有debug symbol的世界來作debug — — 很快地,我發現是所有 dynamic loading 程式,在musl的ldso啟動時、嘗試mapping shared object時、炸在幫對應的記憶體區段清零的一開頭:
而為何libc-test
沒有壓出這問題,原因是他的動態連結測試,只有在dlopen()的部份,這跟直接elf header插INTERP、kernel loadup直接解掉所有dynamic linked symbol時的code flow是不一樣的。現在locate出這問題後,我可以非常快速地建立出最小化的測資,一個main.c、跟一個不做事的stub function的 foo.so去作link,然後開始debug user program,往後這部份的debug與測試也不需勞師動眾 abuild 出來了。
下篇,將是開始debug這個dynlink的故事~